<template>
  <div :class="[isTopDirection ? 'flex justify-center' : '']">
    <div
      v-for="(item, index) in messageQueue"
      :key="index"
      class="message max-w-90vw min-h-100rpx max-h-100rpx px-40rpx py-18rpx fixed -z-1 flex flex-center transition-all rounded-lg text-white"
      :class="[
        item._.isShow ? item._.animation : '',
        `type-${item.type}`,
        `${selDirection(item.direction)}`,
      ]"
      :style="{
        top: `${navigationHeight + 5}px`,
        zIndex: `${item._.isShow ? '9999999' : '-1'}`,
        display: item._.isShow ? 'flex' : 'none',
        animationDuration: `${item.animationDuration}ms`,
        marginTop: `${item._.marginTop}rpx`,
        transitionDuration: `${item._.marginTransitionDuration}ms`,
      }">
      <span class="text-white" v-if="item.isShowIcon">
        <i class="fa fa-lg fa-check-circle" v-if="item.type === 'success'" />
        <i class="fa fa-lg fa-warning" v-else-if="item.type === 'warning'" />
        <i class="fa fa-lg fa-exclamation-circle" v-else-if="item.type === 'error'" />
      </span>
      <text class="truncate indent-xs text-white">
        {{ item.text }}
      </text>
    </div>
  </div>
</template>

<script setup lang="ts">
  import {useSystemStore} from '@/store'
  import {MessageConfig, MessageDirection, MessageType} from '@/components/message'

  const systemStore = useSystemStore()
  const {navigationHeight} = storeToRefs(systemStore)
  const messageQueue = ref<Array<MessageConfig>>([])
  let pushReady: boolean = true //允许新消息推送进入消息队列
  let isTopDirection: boolean = false //消息队列显示方向是否为top

  //显示成功消息
  function success(config: MessageConfig): void {
    initMessage('success', config)
  }

  //显示警告消息
  function warning(config: MessageConfig): void {
    initMessage('warning', config)
  }

  //显示错误消息
  function error(config: MessageConfig): void {
    initMessage('error', config)
  }

  defineExpose({success, warning, error})

  /**
   * 初始化消息
   * @param type 消息类型
   * @param config 消息的配置
   */
  const initMessage = (type: MessageType, config: MessageConfig): void => {
    //默认设置
    const defaultConfig: MessageConfig = {
      type: type,
      text: '',
      duration: 2500,
      direction: 'top',
      animationDuration: 800,
      isShowIcon: true
    }
    if (Object.getOwnPropertyNames(config).length) {
      config = Object.assign(defaultConfig, config)
    }
    config._ = {
      isShow: true,
      timer: null,
      marginTop: 0,
      marginTransitionDuration: 0,
      animation: ''
    }
    config.direction == 'top' && (config._.animation = 'animate__animated animate__slideInDown')
    config.direction == 'left' && (config._.animation = 'animate__animated animate__slideInLeft')
    config.direction == 'right' && (config._.animation = 'animate__animated animate__slideInRight')
    const waitTimer = setInterval(() => {
      if (pushReady) {
        clearInterval(waitTimer)
        config._.marginTop = messageQueue.value.length === 0 ? 0 : messageQueue.value.length * 120
        messageQueue.value.push(config)
        let messageTemp = messageQueue.value[messageQueue.value.length - 1]
        messageTemp._.timer = setTimeout(() => {
          messageTemp.animationDuration = 500
          messageTemp._.animation = 'animate__animated animate__fadeOut'
          setTimeout(() => {
            pushReady = false
            messageTemp._.isShow = false
            changeMarginTop(messageQueue.value.indexOf(messageTemp))
            setTimeout(() => {
              messageQueue.value.splice(messageQueue.value.indexOf(messageTemp), 1)
              pushReady = true
            }, 500)
          }, messageTemp.animationDuration)
          clearTimeout(messageTemp._.timer)
          messageTemp._.timer = null
        }, config.duration)
      }
    }, 100)
  }

  /**
   * 改变消息队列的顶部外边距
   * @param index 删除消息的索引值
   */
  const changeMarginTop = (index: number): void => {
    messageQueue.value.map(item => {
      item._.animation = ''
      if (messageQueue.value.indexOf(item) > index) {
        item._.marginTransitionDuration = 500
        item._.marginTop = (messageQueue.value.indexOf(item) - 1) * 120
        setTimeout(() => {
          item._.marginTransitionDuration = 0
        }, 500)
      } else if (messageQueue.value.indexOf(item) < index) {
        item._.marginTop = messageQueue.value.indexOf(item) * 120
      }
    })
  }

  /**
   * 选择消息显示的方向，用于设置样式
   * @param direction 消息的显示方向
   * @return {string} 样式类名
   */
  const selDirection = (direction: MessageDirection): string => {
    if (direction === 'top') {
      isTopDirection = true
      return ''
    }
    return `${direction}-direction`
  }
</script>

<style scoped lang="scss">
  @import 'message';
</style>